#include "stdafx.h"
#include "PF_commands.h"

#include "pf_dialogfactory.h"

PF_Commands* PF_Commands::uniqueInstance = NULL;


/**
 * Constructor. Initiates main command dictionary.
 */
PF_Commands::PF_Commands() {
	// draw:
        mainCommands.insert(tr("point"), LX_Define::ActionDrawPoint);
        shortCommands.insert(tr("po"), LX_Define::ActionDrawPoint);
	
        mainCommands.insert(tr("line"), LX_Define::ActionDrawLine);
        shortCommands.insert(tr("ln"), LX_Define::ActionDrawLine);
        shortCommands.insert(tr("l"), LX_Define::ActionDrawLine);
	
        mainCommands.insert(tr("polyline"), LX_Define::ActionDrawPolyline);

    mainCommands.insert(tr("offset"), LX_Define::ActionDrawLineParallel);
        shortCommands.insert(tr("o", "offset"), LX_Define::ActionDrawLineParallel);
    mainCommands.insert(tr("parallel"), LX_Define::ActionDrawLineParallel);
        shortCommands.insert(tr("par", "parallel"), LX_Define::ActionDrawLineParallel);

        mainCommands.insert(tr("arc"), LX_Define::ActionDrawArc3P);
        shortCommands.insert(tr("a"), LX_Define::ActionDrawArc3P);
	
        mainCommands.insert(tr("circle"), LX_Define::ActionDrawCircle);
        shortCommands.insert(tr("ci"), LX_Define::ActionDrawCircle);
	
        mainCommands.insert(tr("rectangle"), LX_Define::ActionDrawLineRectangle);
        shortCommands.insert(tr("rec"), LX_Define::ActionDrawLineRectangle);
        shortCommands.insert(tr("rectang"), LX_Define::ActionDrawLineRectangle);
	
        mainCommands.insert(tr("polyline"), LX_Define::ActionDrawPolyline);
	
        mainCommands.insert(tr("text"), LX_Define::ActionDrawText);

	// zoom:
        mainCommands.insert(tr("regen"), LX_Define::ActionZoomRedraw);
        shortCommands.insert(tr("rg", "zoom - redraw"), LX_Define::ActionZoomRedraw);
        shortCommands.insert(tr("zr", "zoom - redraw"), LX_Define::ActionZoomRedraw);
	
        mainCommands.insert(tr("zw", "zoom - window"), LX_Define::ActionZoomWindow);
	
        mainCommands.insert(tr("za", "zoom - auto"), LX_Define::ActionZoomAuto);
	
        mainCommands.insert(tr("zp", "zoom - pan"), LX_Define::ActionZoomPan);
	
        mainCommands.insert(tr("zv", "zoom - previous"), LX_Define::ActionZoomPrevious);

	// edit:
        mainCommands.insert(tr("undo"), LX_Define::ActionEditUndo);
        shortCommands.insert(tr("u", "undo"), LX_Define::ActionEditUndo);
	
        mainCommands.insert(tr("redo"), LX_Define::ActionEditRedo);
        shortCommands.insert(tr("r"), LX_Define::ActionEditRedo);

    // dimensions:
    mainCommands.insert(tr("da", "dimension - aligned"), LX_Define::ActionDimAligned);
    shortCommands.insert(tr("da"), LX_Define::ActionDimAligned);
    
    mainCommands.insert(tr("dh", "dimension - horizontal"), LX_Define::ActionDimLinearHor);
    shortCommands.insert(tr("dh"), LX_Define::ActionDimLinearHor);
    
    mainCommands.insert(tr("dr", "dimension - linear"), LX_Define::ActionDimLinear);
    shortCommands.insert(tr("dr"), LX_Define::ActionDimLinear);

    mainCommands.insert(tr("dv", "dimension - vertical"), LX_Define::ActionDimLinearVer);
    shortCommands.insert(tr("dv"), LX_Define::ActionDimLinearVer);

    mainCommands.insert(tr("ld", "dimension - leader"), LX_Define::ActionDimLeader);
    shortCommands.insert(tr("ld"), LX_Define::ActionDimLeader);

	// tools:
        mainCommands.insert(tr("dimregen"), LX_Define::ActionToolRegenerateDimensions);

    // modify:
    mainCommands.insert(tr("tm", "modify - multi trim (extend)"), LX_Define::ActionModifyTrim2);
    shortCommands.insert(tr("tm"), LX_Define::ActionModifyTrim2);

    mainCommands.insert(tr("xt", "modify - trim (extend)"), LX_Define::ActionModifyTrim);
    shortCommands.insert(tr("xt"), LX_Define::ActionModifyTrim);

    mainCommands.insert(tr("rm", "modify - trim"), LX_Define::ActionModifyTrim);
    shortCommands.insert(tr("rm"), LX_Define::ActionModifyTrim);

    mainCommands.insert(tr("mv", "modify - move"), LX_Define::ActionModifyMove);
    shortCommands.insert(tr("mv"), LX_Define::ActionModifyMove);

    mainCommands.insert(tr("ch", "modify - bevel (chamfer)"), LX_Define::ActionModifyBevel);
    shortCommands.insert(tr("ch"), LX_Define::ActionModifyBevel);

    mainCommands.insert(tr("mi", "modify - mirror"), LX_Define::ActionModifyMirror);
    shortCommands.insert(tr("mi"), LX_Define::ActionModifyMirror);

    mainCommands.insert(tr("ro", "modify - rotate"), LX_Define::ActionModifyRotate);
    shortCommands.insert(tr("ro"), LX_Define::ActionModifyRotate);

    mainCommands.insert(tr("sz", "modify - scale"), LX_Define::ActionModifyMove);
    shortCommands.insert(tr("sz"), LX_Define::ActionModifyMove);

    mainCommands.insert(tr("ss", "modify - stretch"), LX_Define::ActionModifyStretch);
    shortCommands.insert(tr("ss"), LX_Define::ActionModifyStretch);

    mainCommands.insert(tr("er", "modify - delete (erase)"), LX_Define::ActionModifyDelete);
    shortCommands.insert(tr("er"), LX_Define::ActionModifyDelete);

    mainCommands.insert(tr("oo", "modify - undo (oops)"), LX_Define::ActionEditUndo);
    shortCommands.insert(tr("oo"), LX_Define::ActionEditUndo);

    mainCommands.insert(tr("uu", "modify - redo"), LX_Define::ActionEditRedo);
    shortCommands.insert(tr("uu"), LX_Define::ActionEditRedo);

    mainCommands.insert(tr("xp", "modify - explode"), LX_Define::ActionBlocksExplode);
    shortCommands.insert(tr("xp"), LX_Define::ActionBlocksExplode);

    // snap:
    mainCommands.insert(tr("os", "snap - none"), LX_Define::ActionSnapFree);
    shortCommands.insert(tr("os"), LX_Define::ActionSnapFree);

    mainCommands.insert(tr("sg", "snap - grid"), LX_Define::ActionSnapGrid);
    shortCommands.insert(tr("sg"), LX_Define::ActionSnapGrid);

    mainCommands.insert(tr("se", "snap - end"), LX_Define::ActionSnapEndpoint);
    shortCommands.insert(tr("se"), LX_Define::ActionSnapEndpoint);

    mainCommands.insert(tr("si", "snap - intersection"), LX_Define::ActionSnapIntersection);
    shortCommands.insert(tr("si"), LX_Define::ActionSnapIntersection);

    mainCommands.insert(tr("sn", "snap - center"), LX_Define::ActionSnapCenter);
    shortCommands.insert(tr("sn"), LX_Define::ActionSnapCenter);

    mainCommands.insert(tr("sm", "snap - middle"), LX_Define::ActionSnapMiddle);
    shortCommands.insert(tr("sm"), LX_Define::ActionSnapMiddle);

    mainCommands.insert(tr("sn", "snap - nearest"), LX_Define::ActionSnapMiddle);
    shortCommands.insert(tr("sn"), LX_Define::ActionSnapMiddle);

    mainCommands.insert(tr("np", "snap - nearest point"), LX_Define::ActionSnapOnEntity);
    shortCommands.insert(tr("np"), LX_Define::ActionSnapOnEntity);

    // selection:
    mainCommands.insert(tr("tn", "Deselect all"), LX_Define::ActionDeselectAll);
    shortCommands.insert(tr("tn"), LX_Define::ActionDeselectAll);
}

	

/**
 * Tries to complete the given command (e.g. when tab is pressed).
 */
QStringList PF_Commands::complete(const QString& cmd) {
    QStringList ret;
    QHash<QString, LX_Define::ActionType>::const_iterator it = mainCommands.constBegin();
    while (it != mainCommands.constEnd()) {
        if (it.key().startsWith(cmd)) {
            ret << it.key();
        }
        ++it;
    }
	ret.sort();

	return ret;
}



/**
 * @return Command for triggering the given action in the currently chosen
 * language for commands.
 *
 * @param action ID of the action who's command will be returned.
 * @param num Number of the command. There might be multiple commands
 *            for the same action (e.g. 'line' and 'l')
 *
 * @return The translated command.
 */
LX_Define::ActionType PF_Commands::cmdToAction(const QString& cmd) {
    QString c = cmd.toLower();
    QString full = cmd;          // full command defaults to given command
    LX_Define::ActionType ret = LX_Define::ActionNone;

        // find command:
//	LX_Define::ActionType* retPtr = mainCommands.value(cmd);
        if ( mainCommands.contains(cmd) ) {
                ret = mainCommands.value(cmd);
        } else
        if ( shortCommands.contains(cmd) ) {
                ret = shortCommands.value(cmd);
	}

        // find full command to confirm to user:

        QHash<QString, LX_Define::ActionType>::const_iterator it = mainCommands.constBegin();
        while (it != mainCommands.constEnd()) {
                if (it.value()==ret) {
			if (PF_DialogFactory::instance()!=NULL) {
				//if (PF_DIALOGFACTORY!=NULL) {
					PF_DEBUG->print("PF_Commands::cmdToAction: "
						"commandMessage");
					//PF_DIALOGFACTORY->commandMessage(tr("Command: %1")
					//	.arg(full));
					PF_DialogFactory::instance()->commandMessage(
						tr("Command: %1").arg(full));
					PF_DEBUG->print("PF_Commands::cmdToAction: "
						"commandMessage: ok");
				//}
			}
			else {
				PF_DEBUG->print("PF_Commands::cmdToAction: dialog "
				  "factory instance is NULL");
			}
                        break;
                }
            ++it;
        }

	return ret;
}



/**
 * Gets the action for the given keycode. A keycode is a sequence
 * of key-strokes that is entered like hotkeys.
 */
LX_Define::ActionType PF_Commands::keycodeToAction(const QString& code) {
    QString c = code.toLower();
    LX_Define::ActionType ret = LX_Define::ActionNone;

    // draw:
    if (c==tr("po", "point")) {
        ret = LX_Define::ActionDrawPoint;
    } else if (c==tr("li", "line")) {
        ret = LX_Define::ActionDrawLine;
    } else if (c==tr("pa", "parallel")) {
        ret = LX_Define::ActionDrawLine;
    } else if (c==tr("re", "rectangle")) {
        ret = LX_Define::ActionDrawLineRectangle;
    } else if (c==tr("rp", "regular polygon")) {
        ret = LX_Define::ActionDrawLinePolygon;
    } else if (c==tr("ci", "circle")) {
        ret = LX_Define::ActionDrawCircle;
    } else if (c==tr("c2", "2 point circle")) {
        ret = LX_Define::ActionDrawCircle2P;
    } else if (c==tr("c3", "3 point circle")) {
        ret = LX_Define::ActionDrawCircle3P;
    } else if (c==tr("ar", "arc")) {
        ret = LX_Define::ActionDrawArc;
    } else if (c==tr("a3", "3 point arc")) {
        ret = LX_Define::ActionDrawArc3P;
    } else if (c==tr("ep", "ellipse")) {
        ret = LX_Define::ActionDrawEllipseAxis;
    } else if (c==tr("tx", "text") || c==tr("mt", "text")) {
        ret = LX_Define::ActionDrawText;
    }

	// dimensions:
    else if (c==tr("da", "dimension - aligned")) {
        ret = LX_Define::ActionDimAligned;
    } else if (c==tr("dh", "dimension - horizontal")) {
        ret = LX_Define::ActionDimLinearHor;
    } else if (c==tr("dv", "dimension - vertical")) {
        ret = LX_Define::ActionDimLinearVer;
    } else if (c==tr("dr", "dimension - linear")) {
        ret = LX_Define::ActionDimLinear;
    } else if (c==tr("ld", "dimension - leader")) {
        ret = LX_Define::ActionDimLeader;
	}

    // zoom:
    else if (c==tr("rd", "redraw")) {
        ret = LX_Define::ActionZoomRedraw;
    } else if (c==tr("zw", "zoom - window")) {
        ret = LX_Define::ActionZoomWindow;
    } else if (c==tr("za", "zoom - auto")) {
        ret = LX_Define::ActionZoomAuto;
    } else if (c==tr("zi", "zoom - in")) {
        ret = LX_Define::ActionZoomIn;
    } else if (c==tr("zo", "zoom - out")) {
        ret = LX_Define::ActionZoomOut;
    } else if (c==tr("zp", "zoom - pan")) {
        ret = LX_Define::ActionZoomPan;
    } else if (c==tr("zv", "zoom - previous")) {
        ret = LX_Define::ActionZoomPrevious;
    }

	// snap:
	else if (c==tr("os", "snap - none")) {
		ret = LX_Define::ActionSnapFree;
	} else if (c==tr("sg", "snap - grid")) {
		ret = LX_Define::ActionSnapGrid;
	} else if (c==tr("se", "snap - end")) {
		ret = LX_Define::ActionSnapEndpoint;
	} else if (c==tr("si", "snap - intersection")) {
		ret = LX_Define::ActionSnapIntersection;
	} else if (c==tr("sn", "snap - center")) {
		ret = LX_Define::ActionSnapCenter;
	} else if (c==tr("sm", "snap - middle")) {
		ret = LX_Define::ActionSnapMiddle;
	} else if (c==tr("sn", "snap - nearest")) {
		ret = LX_Define::ActionSnapMiddle;
	} else if (c==tr("np", "snap - nearest point")) {
		ret = LX_Define::ActionSnapOnEntity;
	}

	// layer:
	else if (c==tr("fr*", "layers - freeze all")) {
		ret = LX_Define::ActionLayersFreezeAll;
	} else if (c==tr("th*", "layers - defreeze all")) {
		ret = LX_Define::ActionLayersDefreezeAll;
	}

	// selection:
	else if (c==tr("tn", "Deselect all")) {
		ret = LX_Define::ActionDeselectAll;
	}

	// modify:
	else if (c==tr("ch", "modify - bevel (chamfer)")) {
		ret = LX_Define::ActionModifyBevel;
	} else if (c==tr("tm", "modify - multi trim (extend)")) {
		ret = LX_Define::ActionModifyTrim2;
	} else if (c==tr("xt", "modify - trim (extend)")) {
		ret = LX_Define::ActionModifyTrim;
	} else if (c==tr("rm", "modify - trim")) {
		ret = LX_Define::ActionModifyTrim;
	} else if (c==tr("mv", "modify - move")) {
		ret = LX_Define::ActionModifyMove;
	} else if (c==tr("mi", "modify - mirror")) {
		ret = LX_Define::ActionModifyMirror;
	} else if (c==tr("ro", "modify - rotate")) {
		ret = LX_Define::ActionModifyRotate;
	} else if (c==tr("sz", "modify - scale")) {
		ret = LX_Define::ActionModifyMove;
	} else if (c==tr("ss", "modify - stretch")) {
		ret = LX_Define::ActionModifyStretch;
	} else if (c==tr("er", "modify - delete (erase)")) {
		ret = LX_Define::ActionModifyDelete;
	} else if (c==tr("oo", "modify - undo (oops)")) {
		ret = LX_Define::ActionEditUndo;
	} else if (c==tr("uu", "modify - redo")) {
		ret = LX_Define::ActionEditRedo;
	} else if (c==tr("xp", "modify - explode") || 
			c==tr("ex", "modify - explode")) {
		ret = LX_Define::ActionBlocksExplode;
	}

    return ret;
}


/**
 * @return translated command for the given English command.
 */
QString PF_Commands::command(const QString& cmd) {
    if (cmd=="angle") {
        return tr("angle");
    } else if (cmd=="close") {
        return tr("close");
    } else if (cmd=="chord length") {
        return tr("chord length");
    } else if (cmd=="columns") {
        return tr("columns");
    } else if (cmd=="columnspacing") {
        return tr("columnspacing");
    } else if (cmd=="factor") {
        return tr("factor");
    } else if (cmd=="length") {
        return tr("length");
    } else if (cmd=="length1") {
        return tr("length1");
    } else if (cmd=="length2") {
        return tr("length2");
    } else if (cmd=="number") {
        return tr("number");
    } else if (cmd=="radius") {
        return tr("radius");
    } else if (cmd=="rows") {
        return tr("rows");
    } else if (cmd=="rowspacing") {
        return tr("rowspacing");
    } else if (cmd=="text") {
        return tr("text");
    } else if (cmd=="through") {
        return tr("through");
    } else if (cmd=="trim") {
        return tr("trim");
    } else if (cmd=="undo") {
        return tr("undo");
    } else if (cmd=="back") {
        return tr("back");
    }

    PF_DEBUG->print(PF_Debug::D_WARNING,
                "PF_Commands::command: command '%s' unknown", cmd.toLatin1().data());
    return "";
}



/**
 * Checks if the given string 'str' matches the given command 'cmd' for action
 * 'action'.
 *
 * @param cmd The command we want to check for (e.g. 'angle').
 * @param action The action which wants to know.
 * @param str The string typically entered by the user.
 */
bool PF_Commands::checkCommand(const QString& cmd, const QString& str,
                               LX_Define::ActionType /*action*/) {

    QString strl = str.toLower();

    if (cmd=="angle") {
        if (strl==tr("angle") || strl==tr("ang", "angle") ||
                strl==tr("a", "angle")) {
            return true;
        }
    } else if (cmd=="center") {
        if (strl==tr("center") || strl==tr("cen", "center") ||
                strl==tr("c", "center")) {
            return true;
        }
    } else if (cmd=="chord length") {
        if (strl==tr("length", "chord length") ||
                strl==tr("l", "chord length")) {
            return true;
        }
    } else if (cmd=="close") {
        if (strl==tr("close") ||
                strl==tr("c", "close")) {
            return true;
        }
    } else if (cmd=="columns") {
        if (strl==tr("columns") || strl==tr("cols", "columns") ||
                strl==tr("c", "columns")) {
            return true;
        }
    } else if (cmd=="columnspacing") {
        if (strl==tr("columnspacing", "columnspacing for inserts") ||
                strl==tr("colspacing", "columnspacing for inserts") ||
                strl==tr("cs", "columnspacing for inserts")) {
            return true;
        }
    } else if (cmd=="factor") {
        if (strl==tr("factor") || strl==tr("fact", "factor") ||
                strl==tr("f", "factor")) {
            return true;
        }
    } else if (cmd=="help") {
        if (strl==tr("help") || strl==tr("?", "help")) {
            return true;
        }
    } else if (cmd=="length") {
        if (strl==tr("length", "length") ||
                strl==tr("len", "length") ||
                strl==tr("l", "length")) {
            return true;
        }
    } else if (cmd=="length1") {
        if (strl==tr("length1", "length1") ||
                strl==tr("len1", "length1") ||
                strl==tr("l1", "length1")) {
            return true;
        }
    } else if (cmd=="length2") {
        if (strl==tr("length2", "length2") ||
                strl==tr("len2", "length2") ||
                strl==tr("l2", "length2")) {
            return true;
        }
    } else if (cmd=="number") {
        if (strl==tr("number") ||
                strl==tr("num", "number") ||
                strl==tr("n", "number")) {
            return true;
        }
    } else if (cmd=="radius") {
        if (strl==tr("radius") ||
                strl==tr("r", "radius")) {
            return true;
        }
    } else if (cmd=="reversed") {
        if (strl==tr("reversed", "reversed arc") ||
                strl==tr("rev", "reversed arc") ||
                strl==tr("r", "reversed arc")) {
            return true;
        }
    } else if (cmd=="rows") {
        if (strl==tr("rows") || strl==tr("r", "rows")) {
            return true;
        }
    } else if (cmd=="rowspacing") {
        if (strl==tr("rowspacing", "rowspacing for inserts") ||
                strl==tr("rs", "rowspacing for inserts")) {
            return true;
        }
    } else if (cmd=="text") {
        if (strl==tr("text") ||
                strl==tr("t", "text")) {
            return true;
        }
    } else if (cmd=="through") {
        if (strl==tr("through") ||
                strl==tr("t", "through")) {
            return true;
        }
    } else if (cmd=="undo") {
        if (strl==tr("undo") ||
                strl==tr("u", "undo")) {
            return true;
        }
    } else if (cmd=="back") {
        if (strl==tr("back") ||
                strl==tr("b", "back")) {
            return true;
        }
    }

    return false;
}


/**
 * @return the local translation for "Commands available:".
 */
QString PF_Commands::msgAvailableCommands() {
    return tr("Available commands:");
}


// EOF
